<template>
<div class="right-last-use full-height relative-position">
  <!--  头部-->
  <div class="recycle-head row no-wrap bg-primary text-white">
  </div>
  <q-table class="table-file" :pagination="pagination" no-data-label="暂无数据"
           :data="files" :columns="columns" row-key="id" hide-bottom
           binary-state-sort @request="onRequest">
    <template v-slot:body="props">
      <file-item-tr :file="props" :is-active="isActDay(props.row)" :ref="'fileItemTr'+props.row.id"
                    @setFile="setFile"
                    @setNewNameFun="setNewNameFun" @deleteFun="deleteFun"
                    @addCompareList="addCompareList" @setDragItem="setDragItem"
                    @editFile="editFile" @showVersionList="showVersionList"
      />
    </template>
  </q-table>
  <!--  文件内容编辑-->
  <code-edit ref="codeEdit" :value="editFileContent" :name="editFileName" :decode="edtiFileDecode"
             :path="editFilePath" :state="codeState" @refreshList="getInfo" @save="saveFile" />
  <!--  文件对比列表-->
  <compare-file ref="CompareFile"
                :client="client" :requestId="requestId"
                :drag-item="dragItem" :stat-pos="statPos" @compare="compareDetail" />
  <!--  版本履历-->
  <version-list ref="versionList"></version-list>
  <!--  文件内容对比查看-->
  <code-merge ref="codeMerge"></code-merge>
</div>
</template>

<script>
import FileItemTr from './file-item-tr'
import CodeEdit from 'src/components/code-edit/index'
import CompareFile from './compare-file1'
import VersionList from './version-list'
import CodeMerge from 'src/components/code-merge'
import { matchFileType, getFiletype } from 'src/assets/js/util'
import { editFile, setNewName,
  rmDir, readFile, readFile as readFileCloud } from 'src/boot/program/cloud'
import { readFile as readFileLocal } from 'src/assets/js/file-dir'
import { cncToBox, fileMachineLocal } from 'src/boot/program/machine'
import boxErr from 'src/assets/json/boxErr'
import boxCodeErr from 'src/assets/json/boxCodeErr'
import { getLastUseList, rmFileToRecyclebin } from 'src/boot/program/G-gov'
import { mapGetters } from 'vuex'
import fileMqttMixin from 'src/assets/js/file-mqtt-mixin'

export default {
  name: 'right-last-use',
  mixins: [fileMqttMixin],
  data () {
    return {
      columns: [ // 列表的头部
        { name: 'label', align: 'left', label: '文件名', field: 'label', style: 'width: 60%' },
        { name: 'size', align: 'left', label: '大小', field: 'size' },
        { name: 'timestamp', label: '修改时间', field: 'timestamp', sortable: true }
      ],
      pagination: {
        sortBy: '',
        descending: false,
        page: 1,
        rowsPerPage: 0,
        rowsNumber: 10
      },
      files: [], // 列表数据
      loading: false, // 加载状态
      actFile: [], // 选中的文件
      // 编辑内容
      editCurFile: null, // 存储要编辑的文件数据
      editFileContent: '', // 要编辑文件的内容
      editFileName: '', // 要编辑文件的名字
      edtiFileDecode: '', // 要编辑文件的编码
      editFilePath: '', // 要编辑文件的路径
      codeState: 'edit', // 添加编辑状态，edit or add
      // 拖动
      dragItem: [], // 存储拖动的数据
      // 文件对比
      compareList: [], // 文件对比数据
      statPos: 'localCloud' // 定义埋点位置
    }
  },
  computed: {
    ...mapGetters(['userInfo'])
  },
  created () {
    this.getInfo()
  },
  methods: {
    getInfo () {
      this.loading = true
      getLastUseList().then((res) => {
        this.files = this.initInfo(res.data, true)
      }).finally(() => {
        this.loading = false
      })
    },
    /**
     * 给数据添加必要的属性
     * @param info
     * @param isFile 是否是文件
     * @returns 新数据
     */
    initInfo (info, isFile, dirLength = 0) {
      return info.map((item, index) => {
        let type = isFile ? getFiletype(item.label) : 'other'
        return {
          ...item,
          _name: item.label,
          isFile: isFile,
          type,
          source: 'cloud',
          icon: isFile ? 'img:statics/svg/' + type + '.svg' : 'img:statics/svg/file-icon.svg',
          children: []
        }
      })
    },
    // 排序
    onRequest (props) {
      const { sortBy, descending } = props.pagination
      if (sortBy) {
        const sortFn = (descending
          ? (a, b) => (a[sortBy] > b[sortBy] ? -1 : a[sortBy] < b[sortBy] ? 1 : 0)
          : (a, b) => (a[sortBy] > b[sortBy] ? 1 : a[sortBy] < b[sortBy] ? -1 : 0)
        )
        this.files = this.files.sort(sortFn)
        this.pagination.sortBy = sortBy
        this.pagination.descending = descending
      }
    },
    // 是否是选中状态
    isActDay (file) {
      const index = this.actFile.findIndex(item => {
        return item.id === file.id
      })
      return index > -1
    },
    // 选中一个文件
    setFile (item) {
      this.actFile = [item]
    },
    // 重命名文件夹、文件
    setNewNameFun (item, rename) {
      let path = item.isFile ? item.path : item.path.slice(0, item.path.length - 1)
      const params = {
        newKey: rename,
        oldKey: path
      }
      let ref = (this.lookStatus === 'bigIcon' ? 'fileItem' : 'fileItemTr') + item.id
      setNewName(params).then(res => {
        if (this.$refs[ref].edit) {
          this.$refs[ref].edit = false
        } else {
          this.$refs[ref][0].edit = false
        }
        this.getInfo()
      }).catch(() => {
        if (this.$refs[ref].rename) {
          this.$refs[ref].rename = item.label
        } else {
          this.$refs[ref][0].rename = item.label
        }
      })
    },
    // 删除文件和文件夹
    deleteFun (item) {
      this.$q.dialog({
        title: `<p class="dialog-notice-title">
<i class="iconfont icontubiao-28" ></i> 确定要删除${item.label}吗？</p>`,
        html: true,
        ok: {
          unelevated: true,
          label: '确认'
        },
        cancel: {
          unelevated: true,
          outline: true,
          label: '取消'
        }
      }).onOk(data => {
        if (item.isFile) {
          let params = {
            key: item.path,
            size: item.size
          }
          rmFileToRecyclebin(params).then(res => {
            this.getInfo()
          })
        } else {
          let path = item.path
          rmDir(path).then(res => {
            this.getInfo()
          })
        }
      })
    },
    // 编辑读取文件
    editFile (item) {
      if (matchFileType(item.label)) {
        this.errMessage('无法编辑图片文件、word文件、视频文件、音频文件、快捷方式、压缩文件！')
        return
      }
      if (!this.testFileSize(item)) return
      this.editFileName = item.label
      readFile(item.path).then(res => {
        this.editFileContent = res.data
        this.editFilePath = item.path
        this.codeState = 'edit'
        this.editCurFile = item
        this.$refs.codeEdit.showDialog()
      })
    },
    // 验证文件大小是否超过5M
    testFileSize (file) {
      if (file.size > 5 * 1024 * 1024) {
        this.errMessage('文件超过5M暂不支持查看！')
        return false
      }
      return true
    },
    // 编辑保存文件
    saveFile (fileName, code) {
      const params = {
        key: fileName,
        content: code
      }
      editFile(params).then(res => {
        this.successMessage(`修改文件${this.editFileName}成功`)
        this.getInfo()
        this.$refs.codeEdit.hideDialog()
      })
    },
    // 显示版本履历
    showVersionList (file) {
      this.$refs.versionList.showDialog(file)
    },

    // 下面是文件对比相关
    // 加入对比列表
    addCompareList (file) {
      console.log(file)
      this.$refs.CompareFile.show(file)
      this.actFile = []
    },
    // 读取文件内容，弹出比较弹框
    compareDetail (compareList) {
      if (!this.allowSize(compareList)) {
        return false
      }
      let machineArr = compareList.filter(item => item.source === 'machine')
      let machineFileNum = machineArr.length
      this.compareList = compareList
      this.$q.loading.show()
      // 没有机床文件
      if (machineFileNum === 0) {
        const result = this.readFile(compareList)
        Promise.all(result).then(res => {
          let content1 = {
            title: compareList[0].label,
            content: res[0].data
          }
          let content2 = {
            title: compareList[1].label,
            content: res[1].data
          }
          this.$refs.codeMerge.showDialog(content1, content2)
          this.$refs.CompareFile.hide()
        }).finally(() => {
          this.$q.loading.hide()
        })
      } else if (machineFileNum === 1) {
        // 先读取云端或本地文件
        const result = this.readFile(compareList)
        Promise.all(result).then(res => {
          let content1 = {
            title: compareList[0].label,
            content: res[0].data
          }
          // 再读取机床文件
          this.readMachineFile(machineArr[0], content1)
        })
      } else if (machineFileNum === 2) {
        // 两个都为机床文件的对比
        let machineItem = compareList[0]
        this.readMachineFile(machineItem)
      }
    },
    // 比较文件的大小是否符合规则
    allowSize (compareList) {
      for (let i = 0; i < compareList.length; i++) {
        if (matchFileType(compareList[i].label)) {
          this.errMessage('无法读取图片文件、word文件、视频文件、音频文件、快捷方式、压缩文件！')
          return false
        }
        if (compareList[i].source === 'local' && compareList[i].size > 5 * 1024 * 1024) {
          this.errMessage('无法读取超过5M的本地文件')
          return false
        }
        if (compareList[i].source === 'cloud' && compareList[i].size > 1024 * 1024) {
          this.errMessage('无法读取超过1M的云端文件')
          return false
        }
        if (compareList[i].source === 'machine' && compareList[i].size > 1024 * 1024) {
          this.errMessage('无法读取超过1M的机床文件')
          return false
        }
      }
      return true
    },
    // 读取本地和云端对比文件的内容
    readFile (compareList) {
      let result = []
      compareList.forEach(item => {
        // 读取云端内容
        if (item.source === 'cloud') {
          result.push(readFileCloud(item.path))
        }
        // 读取本地文件内容
        if (item.source === 'local') {
          let getFileLocal = new Promise((resolve, reject) => {
            readFileLocal(item.path,
              () => {
                this.errMessage('文件读取失败')
                reject('文件读取失败')
              },
              (str, decode) => {
                resolve({ data: str })
              })
          })
          result.push(getFileLocal)
        }
      })
      return result
    },
    // 读取设备端文件
    readMachineFile (item, prevContent) {
      if (item.position === 'cnc') {
        this.putMachineInside(item, prevContent)
      } else {
        this.putMachine(item, item.path, prevContent)
      }
    },
    // 开始发送内部存储文件到外部存储文件
    putMachineInside (send, prevContent) {
      let requestId1 = 'webClient' + this.userInfo.user_id.toString() + Date.parse(new Date()).toString()
      // let self = this
      let params1 = {
        boxId: send.boxId,
        cncPath: send.path,
        requestId: requestId1
      }
      this.$emit('onSubscribe', send.boxId)
      cncToBox(params1)
      this.client.onMessageArrived = (message) => {
        let data = JSON.parse(message.payloadString)
        try {
          // 这里是放置对其他消息进行处理
          if (requestId1 === data.request_id && data.hasOwnProperty('error')) {
            if (data.error === 0) {
              this.putMachine(send, data.file_path, prevContent)
            } else {
              this.$q.loading.hide()
              this.errMessage(`文件内容读取失败！${boxErr[data.code]}`)
            }
          }
        } catch (e) {
          console.error(e)
          this.errMessage('文件内容读取失败！')
        }
      }
    },
    // 从机床传输到云端的方法
    putMachine (send, path, prevContent) {
      // let self = this
      let params = {
        boxId: send.boxId,
        fileName: send.label,
        filePath: path,
        fromBox: send.position === 'box' ? 1 : 0
      }
      let requestId
      fileMachineLocal(params).then(res => {
        requestId = res.data.requestId
        // cloudDownloadUrl = res.data.url
        this.onSubscribe2(res.data.requestId)
      })
      this.client.onMessageArrived = (message) => {
        let data = JSON.parse(message.payloadString)
        try {
          // 这里是放置对其他消息进行处理
          if (requestId === data.request_id) {
            if (data.hasOwnProperty('source') && data.source === 'send_result') {
              if (data.code === 200) {
                // 盒子上传到云端已完成，接下来是从云端获取内容
                this.getFileContent(send, data.url, prevContent)
              } else {
                this.$q.loading.hide()
                this.errMessage(`文件${send.label}读取失败！${boxCodeErr[data.code]}`)
              }
            }
          }
        } catch (e) {
          console.error(e)
          this.errMessage('文件内容读取失败')
        }
      }
    },
    // 通过云端接口读取云端文件内容
    getFileContent (send, sendPath, prevContent) {
      readFileCloud(sendPath).then(res => {
        let machineContent = {
          title: send.label,
          content: res.data
        }
        if (prevContent) {
          this.$refs.codeMerge.showDialog(prevContent, machineContent)
          this.$refs.CompareFile.hide()
          this.$q.loading.hide()
        } else {
          let machineItem = this.compareList[1]
          this.readMachineFile(machineItem, machineContent)
        }
      }).catch(() => {
        this.$q.loading.hide()
      })
    },
    // 存储拖动数据
    setDragItem (item) {
      this.actFile = [item]
      this.dragItem = [item]
    },

    // 提示
    // 注意提示
    noticeMessage (message) {
      this.$q.dialog({
        title: `<p class="dialog-notice-title">
<i class="iconfont icontubiao-28" ></i> 提示</p>`,
        message: message,
        html: true,
        ok: {
          unelevated: true,
          label: '确认'
        }
      })
    },
    // 成功提示
    successMessage (message) {
      this.$q.dialog({
        title: `<p class="dialog-notice-title">
<i class="iconfont icontubiao-53"></i> ${message}</p>`,
        html: true,
        ok: {
          unelevated: true,
          label: '确认'
        }
      })
    },
    // 失败提示
    errMessage (message) {
      this.$q.dialog({
        title: `<p class="dialog-notice-title">
<i class="iconfont icontubiao-52" ></i> 提示</p>`,
        message: message,
        html: true,
        ok: {
          unelevated: true,
          label: '确认'
        }
      })
    }
  },
  components: {
    FileItemTr,
    CodeEdit,
    CompareFile,
    VersionList,
    CodeMerge
  }
}
</script>

<style scoped lang="stylus">
.right-last-use{
  .recycle-head{
    padding 0 20px
    height 40px
    line-height 40px
    /*font-size 14px*/
    align-items center
    font-size 12px
    .icon{
      margin-left 10px
      font-size 18px
    }
  }
}
</style>
<style lang="stylus">
.right-last-use .table-file{
  height 100%
  .q-table__middle{
    height calc(100% - 40px)
  }
}
</style>
